﻿namespace Nintest.Tests.Collections
{
    using Nintest.Collections;

    using NUnit.Framework;

    [TestFixture]
    public class LookupTestsWithDefaultKey
    {
        private object _nonDefaultKey;
        private Lookup<object, int, Grouping<object, int>> _lookup;
        private Grouping<object, int> _grouping;
        private object _missingKey;

        [SetUp]
        public void SetUp()
        {
            _nonDefaultKey = new object();
            _missingKey = new object();
            _grouping = new Grouping<object, int>(null) { 3, 2, 1 };
            _lookup = new Lookup<object, int, Grouping<object, int>> { _grouping };
        }

        [Test]
        public void Count()
        {
            Assert.That(_lookup.Count, Is.EqualTo(1));
        }

        [Test]
        public void Index_NonDefaultKey()
        {
            var groupingEnumerable = _lookup[_nonDefaultKey];

            Assert.That(groupingEnumerable, Is.Empty);
        }

        [Test]
        public void Index_DefaultKey()
        {
            var groupingEnumerable = _lookup[null];

            Assert.That(groupingEnumerable, Is.EquivalentTo(new[] { 3, 2, 1 }));
        }

        [Test]
        public void Index_MissingKey()
        {
            var groupingEnumerable = _lookup[_missingKey];

            Assert.That(groupingEnumerable, Is.Empty);
        }

        [Test]
        public void TryGetGrouping_NonDefaultKey()
        {
            Grouping<object, int> grouping;

            var success = _lookup.TryGetGrouping(_nonDefaultKey, out grouping);

            Assert.That(success, Is.False);
            Assert.That(grouping, Is.Null);
        }

        [Test]
        public void TryGetGrouping_DefaultKey()
        {
            Grouping<object, int> grouping;

            var success = _lookup.TryGetGrouping(null, out grouping);

            Assert.That(success, Is.True);
            Assert.That(grouping, Is.SameAs(_grouping));
        }

        [Test]
        public void TryGetGrouping_MissingKey()
        {
            Grouping<object, int> grouping;

            var success = _lookup.TryGetGrouping(_missingKey, out grouping);

            Assert.That(success, Is.False);
            Assert.That(grouping, Is.Null);
        }

        [Test]
        public void Contains_NonDefaultKey()
        {
            var actual = _lookup.Contains(_nonDefaultKey);

            Assert.That(actual, Is.False);
        }

        [Test]
        public void Contains_DefaultKey()
        {
            var actual = _lookup.Contains(null);

            Assert.That(actual, Is.True);
        }

        [Test]
        public void Contains_MissingKey()
        {
            var missingKey = new object();

            var actual = _lookup.Contains(missingKey);

            Assert.That(actual, Is.False);
        }

        [Test]
        public void Enumerable()
        {
            var expectedEnumerable = new[] { _grouping };

            Assert.That(_lookup, Is.EquivalentTo(expectedEnumerable));
        }

        [Test]
        public void Add_NonDefaultKey()
        {
            var anotherGrouping = new Grouping<object, int>(_nonDefaultKey);
            var expectedEnumerable = new[] { _grouping, anotherGrouping };

            _lookup.Add(anotherGrouping);

            Assert.That(_lookup, Is.EquivalentTo(expectedEnumerable));
        }

        [Test]
        public void Add_DefaultKey()
        {
            var anotherGrouping = new Grouping<object, int>(null);

            Assert.That(() => _lookup.Add(anotherGrouping), Throws.InvalidOperationException);
        }
    }
}